/*
file: grammar.mly
Arnaud Aujon   AUJA31018906
*/

%{
  open Type
%}

%token <int> INTEGER
%token <float> FLOAT
%token <bool> BOOLEAN
%token <string> VAR STRING OPERATOR_UNARY OPERATOR_BIN 
%token NEWLINE COMMA NIL
%token EQUAL
%token LPAREN RPAREN
%token LBRACKET RBRACKET
%token IF ELSIF ELSE FOR IN DO WHILE END DOT
%token DEF RETURN
%token PRINT 
%token EOF

%right EQUAL


%start expr
%type <Type.t1_expr> expr

%% /* Grammar rules and actions follow */
expr:
    NEWLINE expr                 { $2 }
  | struct_if                    { Struct_If($1) }
  | struct_while                 { $1 }
  | struct_for                   { $1 }
  | assignment                   { $1 }
  | print                        { $1 }
  | decl_function                { $1 }
  | appel_function               { $1 }

print:
  PRINT print_internal           { Print($2) }

print_internal:
    exp                          { [$1] }
  | exp COMMA print_internal     { $1::$3 }

exp:
    INTEGER                      { Int($1) }
  | FLOAT                        { Float($1) }
  | STRING                       { String($1) }
  | BOOLEAN                      { Bool($1) }
  | VAR                          { Var($1) }
  | VAR LBRACKET exp RBRACKET    { Array_index($1, $3) }
  | LPAREN exp RPAREN            { $2 }
  | exp OPERATOR_BIN exp         { Binary($1, $2, $3) }
  | OPERATOR_UNARY exp           { Unary($1, $2) }
  | LBRACKET array_block RBRACKET  { Array($2) }
  | appel_function               { $1 }




array_block:
    exp                          { [$1] }
  | exp COMMA array_block        { $1::$3 }

assignment:
    exp EQUAL exp                { Assignment($1, $3) }



struct_if:
    IF LPAREN exp RPAREN block END                   { [If($3, $5)] }
  | IF LPAREN exp RPAREN block ELSIF struct_elsif    { If($3, $5)::$7 }
  | IF LPAREN exp RPAREN block ELSE struct_else      { If($3, $5)::$7 }

struct_elsif:
    LPAREN exp RPAREN block END                      { [If($2, $4)] }
  | LPAREN exp RPAREN block ELSIF struct_elsif       { If($2, $4)::$6 }
  | LPAREN exp RPAREN block ELSE struct_else         { If($2, $4)::$6}

struct_else:
    block  END                        { [Else($1)] }

block:
  | expr block                        { $1 :: $2 }
  |                                   { [] }


/* while */
struct_while:
  WHILE LPAREN exp RPAREN NEWLINE block END      { While($3, $6) }

/* for */
struct_for:
    FOR VAR IN LPAREN exp DOT DOT exp RPAREN NEWLINE DO NEWLINE block END
                                { For(Var($2), $5, $8, $13) }
  | FOR VAR IN LPAREN exp DOT DOT exp RPAREN NEWLINE block END
                                { For(Var($2), $5, $8, $11) }



/* declaration de fonction */
decl_function:
    DEF VAR LPAREN arg_list_dec RPAREN block_function
                                { Decl_Function($2, $4, $6) }


arg_list_dec:
    VAR                         { [$1] }
  | VAR COMMA arg_list_dec      { $1::$3 }
  |                             { [] }

arg_list:
    exp                         { [$1] }
  | exp COMMA arg_list          { $1::$3 }
  |                             { [] }

block_function:
    END                         { [] }
  | RETURN exp block_function   { Return($2)::$3 }
  | expr block_function         { $1::$2 }

/* appel de fonction, NOTE ne pas l'appeller "function" : 
   reservé par ocamlyacc ! */
appel_function:
    VAR LPAREN arg_list RPAREN  { Function($1, $3) }


%%

